package cn.xhh.dailyreview.client;

import java.util.ArrayList;
import java.util.List;

import cn.xhh.dailyreview.client.utils.ClientUtil;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ButtonBase;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * The panel for creating and editing/displaying a review
 * @author cooky
 */
public class ReviewPanel extends VerticalPanel {
	
	/** current category index */
	private int currentIdx = 0;
	
	private List<String> categories;
	/** review content corresponding to the categories */
	private List<String> reviews;
	
	private final ButtonBase btnSave;
	private Timer autoSave;

	/**
	 * @param categories make sure there is at least on category in it
	 */
	public ReviewPanel(final DailyReview dailyReview, List<String> categories, List<String> reviews) {
		super();
		
		this.reviews = (reviews == null) ? new ArrayList<String>(categories.size()) : reviews;
		
		configOptions(dailyReview);

		HorizontalPanel hTopPanel = new HorizontalPanel();
		hTopPanel.setSpacing(0);
		final HTML htmlPrevious = new HTML(DailyReview.constants.beginning());
		htmlPrevious.setWidth("150px");
		final HTML htmlNext = new HTML(categories.size() > 1 ? categories.get(1) : DailyReview.constants.end());
		htmlNext.setWidth("150px");
		htmlNext.addStyleName("label-next");
		HorizontalPanel hTopmiddPanel = new HorizontalPanel();
		hTopmiddPanel.setSpacing(0);
		final Button btnPrevious = new Button("Previous");
		btnPrevious.setWidth("80px");
		final Button btnNext = new Button("Next");
		btnNext.setWidth("80px");
		final HTML htmlCurrent = new HTML(categories.get(0));
		htmlCurrent.setWidth("150px");
		htmlCurrent.addStyleName("label-current");
		
		HorizontalPanel hMiddPanel = new HorizontalPanel();
		hMiddPanel.setSpacing(3);
		final TextArea taReview = new TextArea();
		taReview.setSize("550px", "350px");
		btnSave = new Button("Save");
		
		setWidth("100%");
		setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
		setSpacing(20);
		
		hTopPanel.add(htmlPrevious);
		hTopmiddPanel.add(btnPrevious);
		hTopmiddPanel.add(htmlCurrent);
		hTopmiddPanel.add(btnNext);
		hTopPanel.add(hTopmiddPanel);
		hTopPanel.add(htmlNext);
		hMiddPanel.add(taReview);
		hMiddPanel.add(btnSave);
		add(hTopPanel);
		add(hMiddPanel);
		
		btnPrevious.setEnabled(false);
		if (categories.size() < 2) btnNext.setEnabled(false);
		
		ClickHandler buttonHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if (event.getSource() == btnPrevious)
					showPrevious();
				else
					showNext();
			}
			private void showPrevious() {
				saveReview();
				if (hasPrevious()) { // TODO
//					htmlNext.setText(getCurrent());
//					htmlCurrent.setText(getPrevious());
//					goPrevious();
//					htmlPrevious.setText(getPrevious());
//					taReview.setText(Review.getCurrentContent());
				}
				if (!hasPrevious())
					btnPrevious.setEnabled(false);
				btnNext.setEnabled(true);
			}
			
			private void showNext() {
				saveReview();
				if (hasNext()) {
//					htmlPrevious.setText(Review.getCurrentItem());
//					htmlCurrent.setText(Review.nextItem());
//					htmlNext.setText(Review.getNextItem());
//					taReview.setText(Review.getCurrentContent());
				}
				if (!hasNext())
					btnNext.setEnabled(false);
				btnPrevious.setEnabled(true);
			}
		};
		btnPrevious.addClickHandler(buttonHandler);
		btnNext.addClickHandler(buttonHandler);
		btnSave.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				updateSaveButton(true);
				ClientUtil.getService().saveReview(ReviewPanel.this.reviews, new AsyncCallback<Boolean>() {
					@Override
					public void onFailure(Throwable caught) {
						updateSaveButton(false);
						ClientUtil.alert("RPC calling failed while saving review.");
					}
					@Override
					public void onSuccess(Boolean result) {
						updateSaveButton(false);
						if (result == null || !result)
							ClientUtil.alert("Saving review failed!");
						else
							ClientUtil.info("Review saved. Review saved. Review saved. Review saved.");
					}
					
				});
			}
		});
		
		final AsyncCallback<Boolean> acAutoSave = new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
				updateSaveButton(false);
				ClientUtil.flash("Auto-saving the review failed.");
			}
			@Override
			public void onSuccess(Boolean result) {
				updateSaveButton(false);
				if (result)
					ClientUtil.flash("Review auto-saved.");
				else
					autoSave.cancel();
			}
		};
		autoSave = new Timer() {
			public void run() {
				updateSaveButton(true);
				ClientUtil.getService().saveReview(ReviewPanel.this.reviews, acAutoSave);
			}
		};
		// auto save review content to server every 1 minute
		autoSave.scheduleRepeating(60 * 1000);
	}
	
	private void configOptions(DailyReview dailyReview) {
		// TODO
	}

	private void saveReview() {
		AsyncCallback<Boolean> acSave = new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
				ClientUtil.flash("Saving the review failed.");
			}
			@Override
			public void onSuccess(Boolean result) {
				if (!result)
					ClientUtil.flash("Saving the review failed.");
			}
		};
		ClientUtil.getService().saveReview(ReviewPanel.this.reviews, acSave);
	}
	
	private boolean hasPrevious() {
		return currentIdx > 0;
	}
	
	private boolean hasNext() {
		return currentIdx < categories.size() - 1;
	}
	
	/**
	 * Update the status of the Save button according to the current action: saving or saved.
	 * @param saving <code>true</code> for preparing to save the review, 
	 * <code>false</code> for review saved (neither succeeded or failed)
	 */
	private void updateSaveButton(boolean saving) {
		if (saving) {
			btnSave.setText("SAVING...");
			btnSave.setEnabled(false);
		} else {
			btnSave.setText("Save");
			btnSave.setEnabled(true);
		}
	}

}
